Skip to content

Exercises

Suppose we're building a Goodreads-type site, a place for users to discover new books. Our job is to implement a search feature:

In the sandbox below, you'll find you have a <SearchResult> component ready to be used to display the results. Your mission is to wire up the search form so that the results are fetched from the backend API. An endpoint has been provided.

Here's an example request/response:

// REQUEST:
GET '/api/book-search?searchTerm=winter'
// RESPONSE:
{
"ok": true,
"results": [
{
"isbn": "1234567890123",
"name": "Winter's Orbit",
"author": "Everina Maxwell",
"coverSrc": "/image-path/cover.png",
"abstract": "While the Iskat Empire has long dominated the system…"
}
]
}

Acceptance Criteria:

There's quite a bit to do in this one!

  • Submitting the form should make a GET request to the supplied API endpoint, passing along searchTerm as a query parameter.
  • If there are search results, we should map over them, rendering a <SearchResult> element for each one.
  • We should show the text "Searching…" while the search is in progress.
  • Before the user has searched, we should show a paragraph containing the text "Welcome to Book Search!"
  • If there are no matching results, we should show a paragraph containing the text "No Results".
  • If the API returns an error, we should show a paragraph containing the text "Something went wrong!".
    • You can simulate an error by passing simulatedError=true as a query parameter.
  • There should be no key warnings in the console.

You don't have to use SWR for this. SWR is primarily useful when fetching data on mount. In this case, it's easier to make the request "on-demand", when the user performs a search.

Code Playground

import React from 'react';

import TextInput from './TextInput.js';
import SearchResult from './SearchResult.js';

/*
API INSTRUCTIONS
This endpoint expects a GET request,
with a query parameter of `searchTerm`.
Eg. `/api/book-search?searchTerm=winter`
To simulate an error, attach the following
query parameter: `simulatedError=true`
To test the results, here are some suggested
search terms:
• `fifth` — 1 result
• `a` — 18 results
• `becky` — 4 results
• `hello` — 0 results
*/

const ENDPOINT =
'https://jor-test-api.vercel.app/api/book-search';

function App() {
const [
searchTerm,
setSearchTerm,
] = React.useState('');
const [
searchResults,
setSearchResults,
] = React.useState(null);

return (
<>
<header>
<form>
<TextInput
required={true}
label="Search"
placeholder="The Fifth Season"
value={searchTerm}
onChange={(event) => {
setSearchTerm(event.target.value);
}}
/>
<button>Go!</button>
</form>
</header>

<main>
<div className="search-results">
<h2>Search Results:</h2>
{/*
Here's an example of the element
we want to render:
*/}
<SearchResult result={EXAMPLE} />
</div>
</main>
</>
);
}

const EXAMPLE = {
isbn: '9781473621442',
name: 'A Closed and Common Orbit',
author: 'Becky Chambers',
coverSrc: 'https://sandpack-bundler.vercel.app/img/book-covers/common-orbit.jpg',
abstract:
"Lovelace was once merely a ship's artificial intelligence. When she wakes up in an new body, following a total system shut-down and reboot, she has no memory of what came before. As Lovelace learns to negotiate the universe and discover who she is, she makes friends with Pepper, an excitable engineer, who's determined to help her learn and grow.",

Solution:

Fetching the current user

In the sandbox below, we want to display a card showing a user's name and email. Before we can do that, however, we need to fetch the user data from the API.

An API endpoint has been provided, which returns data in the following format:

{
"user": {
"name": "Ahmed",
"email": "me@ahmed1234.com",
}
}

Your mission is to fetch the data from the endpoint provided, and pass the received data to the UserCard component. You should also include a loading state, as well as an error state.

Acceptance Criteria:

  • You should use the provided useSWR hook to perform the request.
  • While the request is running, a spinner should be shown. A Spinner component has been provided for this purpose.
  • If the request succeeds, the <UserCard> component should be shown, populated with the data from the request.
  • If the request fails, you can show an error message (a standard paragraph with "Something went wrong!" is fine).
    • You can simulate an error by passing simulatedError=true as a query parameter.

Code Playground

import React from 'react';
import useSWR from 'swr';

import UserCard from './UserCard.js';
import Spinner from './Spinner.js';

/*
API INSTRUCTIONS
This endpoint expects a GET request.
To simulate an error, attach the following
query parameter: `simulatedError=true`
*/

const ENDPOINT =
'https://jor-test-api.vercel.app/api/get-current-user';

function App() {
return (
<UserCard name="Name here" email="Email here" />
);
}

export default App;
preview
console

Solution: